﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#include "GridNameManager.h"
#include "AuxiliaryElementUtils.h"
#include "DbObjectUtils.h"
#include "ElementUtils.h"
#include "IDocument.h"
#include "IElementBasicInformation.h"
#include "IElementModelShape.h"
#include "IElementOffsetComponent.h"
#include "IElementParameterBindings.h"
#include "IElementParameters.h"
#include "IElementParentReporter.h"
#include "IElementPosition.h"
#include "IElementShapeHandle.h"
#include "IElementStatus.h"
#include "IGenericElement.h"
#include "IGraphicsElementShape.h"
#include "IJoinRelationshipBehavior.h"
#include "IParameter.h"
#include "IParameterBinding.h"
#include "IParameterValueElementId.h"
#include "IGeometryRelationshipComponent.h"
#include "UniIdentity.h"

#include "EnableCompileWarning_The_LAST_IncludeInCpp.h"



using namespace gcmp;

DBOBJECT_DATA_DEFINE(GridNameManager)
{
    m_pOwnerElement = nullptr;
    SetLastActiveName__(L"");
    SetNameInitialized__(false);
}

#pragma region 基本属性

gcmp::NdbObject* gcmp::GridNameManager::GetTopOwnerObject() const
{
    return quick_cast<NdbObject>(const_cast<IElement*>(GetOwnerElement()));
}

IDocument * gcmp::GridNameManager::GetDocument() const
{
    if (!m_pOwnerElement)
    {
        return nullptr;
    }
    return m_pOwnerElement->GetDocument();
}

ElementId gcmp::GridNameManager::GetOwnerElementId() const
{
    if (!m_pOwnerElement)
    {
        return ElementId::InvalidID;
    }
    return m_pOwnerElement->GetElementId();
}

bool GridNameManager::SetOwnerElement(IElement* pOwnerElement)
{
    m_pOwnerElement = pOwnerElement;
    return true;
}

#pragma endregion 基本属性

#pragma region 关联更新

void gcmp::GridNameManager::UpdateForWeakParentDeletion(const std::set<ElementId>& deletedElementIds)
{
    IElement* pElement = GetOwnerElement();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pElement, L"IElement为空",L"GDMPLab",L"2024-03-30");

    //参数绑定，并且绑定的不是族参数时
    IElementParameterBindings* pBehavior = GetOwnerElement()->GetElementParameters()->GetElementParameterBindings();
    if (pBehavior)
    {
        auto& bindingInfos = pBehavior->GetParameterBindings();
        for (int ii = (int)bindingInfos.size(); ii > 0; --ii)
        {
            const IParameterBinding* info = bindingInfos[ii - 1].get();
            IElement* pSourceElement = GetDocument()->GetElement(info->GetSourceElementId());
            if (pSourceElement == nullptr)
            {
                continue;
            }

            IElementParameterBindings* pBingBehavior = pSourceElement->GetElementParameters()->GetElementParameterBindings();
            DBG_WARN_AND_RETURN_VOID_UNLESS(pBingBehavior, L"pBingBehavior无效",L"GDMPLab",L"2024-03-30");

            std::vector<RegenDataId> rcDataIds = pBingBehavior->GetParameterRdIdsByParameterDefinitionId(info->GetSourceParameterDefinitionId());
            std::size_t size = rcDataIds.size();
            if (size > 0 && size != 2) // IFamilyManager为2
            {
                if (deletedElementIds.find(info->GetSourceElementId()) != deletedElementIds.end())
                {
                    pBehavior->DeleteParameterBinding(info->GetTargetParameterDefinitionId());
                }
            }
        }
    }
}

void gcmp::GridNameManager::ReportParents(IElementParentReporter& reporter) const
{
    const IElement* pElement = GetOwnerElement();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pElement, L"IElement为空",L"GDMPLab",L"2024-03-30");
    const IElementPosition *posBehavior = pElement->GetElementPosition();
    if (posBehavior != nullptr)
    {
        reporter.ReportStrong(posBehavior->GetBaseAssociatedPlaneId());
    }

    const IGeometryRelationshipComponent* pGeometryRepCpt = pElement->GetGeometryRelationshipComponent();
    if (pGeometryRepCpt
            && pGeometryRepCpt->GetJoinRelationship() != nullptr)
    {
        auto pBehavior = pGeometryRepCpt->GetJoinRelationship();
        reporter.ReportWeak(pBehavior->GetElementJoinIdsAtStart());
        reporter.ReportWeak(pBehavior->GetElementJoinIdsAtEnd());
        reporter.ReportWeak(pBehavior->GetElementJoinIdsAtMiddle());
    }

    const IElementParameterBindings* pBehavior = GetOwnerElement()->GetElementParameters()->GetElementParameterBindings();
    if (pBehavior)
    {
        auto& bindingInfos = pBehavior->GetParameterBindings();
        FOR_EACH(info, bindingInfos)
        {
            IElement* pSourceElement = GetDocument()->GetElement(info->GetSourceElementId());
            if (pSourceElement != nullptr)
            {
                reporter.ReportWeak(pSourceElement->GetElementId());
            }
        }
    }

    auto& embeddedParamMap = GetOwnerElement()->GetElementParameters()->GetEmbeddedParametersMap();
    FOR_EACH(iter, embeddedParamMap)
    {
        const IParameterValueElementId *pElementIdParamValue = dynamic_cast<const IParameterValueElementId *>(iter.second->GetParameterValueStorage());
        if (pElementIdParamValue != nullptr)
        {
            reporter.ReportWeak(pElementIdParamValue->GetValue());
        }
    }

    reporter.ReportStrong(GetOwnerElement()->GetBasicInformation()->GetTypeId());

    const IGraphicsElementShape* pGrep = pElement->GetElementModelShape()->GetGraphicsElementShape();
    if (pGrep)
    {
        std::vector<ElementId> ids;
        pGrep->GetReferencedElementIds(ids);
        reporter.ReportWeak(ids);
    }

}

#pragma endregion 关联更新

#pragma region 其他
bool gcmp::GridNameManager::FinishEditing()
{
    std::vector<ElementId> ids = AuxiliaryElementUtils::GetAuxiliaryElements(GetOwnerElement());
    for (int i = 0; i < (int)ids.size(); i++)
    {
        IElement* pElement = GetDocument()->GetElement(ids[i]);
        IElementShapeHandle* pElementShapeHandle = quick_cast<IElementShapeHandle>(pElement);
        if (pElementShapeHandle)
        {
            pElementShapeHandle->FinishEditing();
            continue;
        }
    }
    return true;
}

#pragma endregion 其他

GridNameManager * gcmp::GridNameManager::Get(IDocument * pDoc)
{
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDoc, L"pDoc为空。",L"GDMPLab",L"2024-03-30");

    IElement* pUniqueElem;
    {
        pUniqueElem = pDoc->GetUniqueElementByClassUid(UniIdentity(GridNameManager::GetGuid()));
    }
    if (!pUniqueElem)
    {
        return nullptr;
    }

    IGenericElement * pGridNameManagerElem = quick_cast<IGenericElement>(pUniqueElem);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pGridNameManagerElem, L"pGridNameManagerElem为空。无法获取轴网编号管理器。",L"GDMPLab",L"2024-03-30");
    GridNameManager * pGridNameManager = quick_cast<GridNameManager>(pGridNameManagerElem->GetExternalObject());
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pGridNameManager, L"pGridNameManager为空。无法获取轴网编号管理器。",L"GDMPLab",L"2024-03-30");

    return pGridNameManager;
}

GridNameManager * gcmp::GridNameManager::Create(IDocument* pDoc)
{
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDoc, L"pDoc为空。",L"GDMPLab",L"2024-03-30");
    GridNameManager* pGridNameManager = GridNameManager::Get(pDoc);
    if (pGridNameManager)
    {
        return pGridNameManager;
    }

    OwnerPtr<GridNameManager> opGridNameManager = NEW_AS_OWNER_PTR(GridNameManager);
    IGenericElement* pGridNameManagerElem = IGenericElement::Create(pDoc, TransferOwnership(opGridNameManager), GridNameManager::GetClassId().GetGuid(), ElementCreationOptions::Normal);
    ElementUtils::MakeElementUnique(pGridNameManagerElem, GridNameManager::GetGuid());

    pGridNameManagerElem->GetStatus()->SetIsVisible(false);
    return quick_cast<GridNameManager>(pGridNameManagerElem->GetExternalObject());
}

std::wstring gcmp::GridNameManager::GetLastActiveName(IDocument* pDoc)
{
    DBG_WARN_AND_RETURN_UNLESS(pDoc, L"", L"pDoc为空。",L"GDMPLab",L"2024-03-30");
    GridNameManager* pGridNameManager = GridNameManager::Get(pDoc);
    DBG_WARN_AND_RETURN_UNLESS(pDoc, L"", L"pGridNameManager为空，请先初始化。",L"GDMPLab",L"2024-03-30");
    return pGridNameManager->GetLastActiveName__();
}

bool gcmp::GridNameManager::SetLastActiveName(IDocument* pDoc, const std::wstring& name)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pDoc, L"pDoc为空。",L"GDMPLab",L"2024-03-30");
    GridNameManager* pGridNameManager = GridNameManager::Get(pDoc);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pDoc, L"pGridNameManager为空，请先初始化。",L"GDMPLab",L"2024-03-30");
    pGridNameManager->SetLastActiveName__(name); 
    pGridNameManager->SetNameInitialized__(true); 
    return true;
}

bool gcmp::GridNameManager::IsNameInitialized(IDocument* pDoc)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pDoc, L"pDoc为空。",L"GDMPLab",L"2024-03-30");
    GridNameManager* pGridNameManager = GridNameManager::Get(pDoc);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pDoc, L"pGridNameManager为空，请先初始化。",L"GDMPLab",L"2024-03-30");
    return pGridNameManager->GetNameInitialized__();
}
